/**
 * 
 */
package org.extdev.libraries.ltr;

import java.nio.DoubleBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.extdev.device.ltr.LTR11Channel;
import org.extdev.device.ltr.LTR11InputMode;
import org.extdev.device.ltr.LTR11StartADCMode;

import com.sun.jna.ptr.IntByReference;

/**
 * @author LAP
 *
 */
public class LTR11APILibraryFacade {

	private LTR11.ByReference ltr11;
	private List<LTR11Channel> channels;
	private LTR11APILibrary dllInstance;
	private LTRAPILibraryFacade ltrFacade;
	private int pointsCount = 100;
	private int timeout;
	private boolean opened = false;
	
	
	public LTR11APILibraryFacade() throws LTRException {
		ltr11 = new LTR11.ByReference();
		inicilizeLTR11();
		ltrFacade = new LTRAPILibraryFacade(ltr11.getPointer());
		channels = new LinkedList<LTR11Channel>();
		dllInstance = LTR11APILibrary.INSTANCE;
	}
	
	private void calcTimeout() {
		timeout = (int) Math.round((pointsCount / (ltr11.chRate * ltr11.lChQnt)) + 1000);
	}
	
	private void channelsToLchTbl() {
		Arrays.fill(ltr11.lChTbl, (byte)0);
		for(int i = 0; i < channels.size(); i++) {
			ltr11.lChTbl[i] = channels.get(i).toByte();
		}
	}
	
	public void addChannel(LTR11Channel value) {
		channels.add(value);
	}
	
	public void removeChannel(LTR11Channel value) {
		channels.remove(value);
	}
	
	public void removeChannel(int index) {
		channels.remove(index);
	}
	
	public int getChannelsCount() {
		return channels.size();
	}
	
	public LTR11Channel getChannel(int index) {
		return channels.get(index);
	}
	
	public void setChannel(int index, LTR11Channel value) {
		channels.set(index, value);
	}
	
	public void inicilizeLTR11() throws LTRException {
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_Init(ltr11));
		calcTimeout();
	}
	
	public void setADC() throws LTRException {
		channelsToLchTbl();
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_SetADC(ltr11));
	}
	
	public void openLTR11() throws LTRException {
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_Open(
				ltr11, 
				ltr11.channel.saddr, 
				ltr11.channel.sport, 
				new String(ltr11.channel.csn), 
				ltr11.channel.cc));
		opened = true;
	}
	
	public void closeLTR11() throws LTRException {
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_Close(ltr11));
		opened = false;
	}
	
	public void startLTR11() throws LTRException {
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_Start(ltr11));
	}
	
	public void stopLTR11() throws LTRException {
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_Stop(ltr11));
	}
	
	@Deprecated
	public IntBuffer getFrame() {
		return null;
	}
	
	public int getPointsCount() {
		return pointsCount;
	}
	
	public void setPointsCount(int value) {
		pointsCount = value;
		calcTimeout();
	}
	
	public int getTimeout() {
		return timeout;
	}
	
	public void setTimeout(int value) {
		timeout = value;
	}
	
	public DoubleBuffer processData(IntBuffer src, boolean calibr, boolean volt) throws LTRException {
		DoubleBuffer dest = DoubleBuffer.allocate(src.capacity());
		LTR11ExceptionGenerator.throwLTRException(dllInstance.LTR11_ProcessData(
				ltr11, 
				src, 
				dest, 
				new IntByReference(src.capacity()), 
				calibr, 
				volt));
		return dest;
	}
	
	public LTRData receive() throws LTRException {
		return ltrFacade.receive(pointsCount * ltr11.lChQnt, getTimeout());
	}
	
	public boolean isOpened() {
		return opened;
	}
	
	public void setStartMode(LTR11StartADCMode value) {
		ltr11.adcMode = value.ordinal();
	}
	
	public LTR11StartADCMode getStartMode() {
		for(LTR11StartADCMode mode : LTR11StartADCMode.values()) {
			if (ltr11.adcMode == mode.ordinal()) {
				return mode;
			}
		}
		throw new IllegalArgumentException("uncnown mode");
	}
	
	public void setInputMode(LTR11InputMode value) {
		ltr11.inputeMode = value.ordinal();
	}
	
	public LTR11InputMode getInputMode() {
		for(LTR11InputMode mode : LTR11InputMode.values()) {
			if (ltr11.adcMode == mode.ordinal()) {
				return mode;
			}
		}
		throw new IllegalArgumentException("uncnown mode");
	}

	public void setChannel(short moduleNo) {
		ltrFacade.setChannel(moduleNo);
	}

	public void setCrateSN(byte[] serialNumber) {
		ltrFacade.setCrateSN(serialNumber);
	}
}
